library(readxl)
# load the data
info_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Rent', range = 'A5:AD851')
asking_rent_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Rent', range = 'AE5:FL851')
rownames(asking_rent_1) = info_1$ProjID
effective_rent_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Rent', range = 'FM5:KT851')
rownames(effective_rent_1) = info_1$ProjID
eff_rnt_per_sq_ft_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Rent', range = 'KU5:QB851')
rownames(eff_rnt_per_sq_ft_1) = info_1$ProjID
occupancy_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Occ & Concession', range = 'AE5:FL851')
rownames(occupancy_1) = info_1$ProjID
concession_value_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Occ & Concession', range = 'FM5:KT851')
rownames(concession_value_1) = info_1$ProjID
concession_percent_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Occ & Concession', range = 'KU5:QB851')
rownames(concession_percent_1) = info_1$ProjID
property_submarket_grade_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Asset Class', range = 'AE5:FL851')
rownames(property_submarket_grade_1) = info_1$ProjID
property_market_grade_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Asset Class', range = 'FM5:KT851')
rownames(property_market_grade_1) = info_1$ProjID
submarket_grade_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Asset Class', range = 'KU5:QB851')
rownames(submarket_grade_1) = info_1$ProjID
property_status_1 = read_excel(path = '~/Documents/Job Application/USAA/MSA1.xlsx', sheet = 'Property Status', range = 'AE5:FL851')
rownames(property_status_1) = info_1$ProjID
info_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Rent', range = 'A5:AD104')
asking_rent_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Rent', range = 'AE5:FL104')
rownames(asking_rent_2) = info_2$ProjID
effective_rent_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Rent', range = 'FM5:KT104')
rownames(effective_rent_2) = info_2$ProjID
eff_rnt_per_sq_ft_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Rent', range = 'KU5:QB104')
rownames(eff_rnt_per_sq_ft_2) = info_2$ProjID
occupancy_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Occ & Concession', range = 'AE5:FL104')
rownames(occupancy_2) = info_2$ProjID
concession_value_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Occ & Concession', range = 'FM5:KT104')
rownames(concession_value_2) = info_2$ProjID
concession_percent_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Occ & Concession', range = 'KU5:QB104')
rownames(concession_percent_2) = info_2$ProjID
property_submarket_grade_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Asset Class', range = 'AE5:FL104')
rownames(property_submarket_grade_2) = info_2$ProjID
property_market_grade_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Asset Class', range = 'FM5:KT104')
rownames(property_market_grade_2) = info_2$ProjID
submarket_grade_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Asset Class', range = 'KU5:QB104')
rownames(submarket_grade_2) = info_2$ProjID
property_status_2 = read_excel(path = '~/Documents/Job Application/USAA/MSA2.xlsx', sheet = 'Property Status', range = 'AE5:FL104')
rownames(property_status_2) = info_2$ProjID
Number of Properties Delivered Since April 2008 by Markets
# Number of properties delivered since April 2008
sprintf('There are %i properties are delivered since April 2008 in %s.', sum(apply(property_status_1, 1, function(x) na.omit(x)[1]) %in% c('LU', 'UC/LU')), unique(info_1$MarketName))
[1] "There are 270 properties are delivered since April 2008 in Austin-Round Rock, TX."
sprintf('There are %i properties are delivered since April 2008 in %s.', sum(apply(property_status_2, 1, function(x) na.omit(x)[1]) %in% c('LU', 'UC/LU')), unique(info_2$MarketName))
[1] "There are 9 properties are delivered since April 2008 in Akron, OH."
Average Lease-Up Time by Markets
# Average lease-up time
delivered_1 <- info_1$ProjID[apply(property_status_1, 1, function(x) na.omit(x)[1]) %in% c('LU', 'UC/LU')]
delivered_2 <- info_2$ProjID[apply(property_status_2, 1, function(x) na.omit(x)[1]) %in% c('LU', 'UC/LU')]
lease_up_time <- function(l){
i <- 0
while(l[[i+1]] < 0.9){
i = i + 1
if (i == length(l)) {
break
}
}
return(i)
}
lease_up_time_1 <- as.numeric(lapply(apply(occupancy_1[rownames(occupancy_1) %in% delivered_1,], 1, function(x) na.omit(x)), lease_up_time))
lease_up_time_2 <- as.numeric(lapply(apply(occupancy_2[rownames(occupancy_2) %in% delivered_2,], 1, function(x) na.omit(x)), lease_up_time))
sprintf('The average lease-up time is %.2f months in %s.', mean(lease_up_time_1), unique(info_1$MarketName))
[1] "The average lease-up time is 11.84 months in Austin-Round Rock, TX."
sprintf('The average lease-up time is %.2f months in %s.', mean(lease_up_time_2), unique(info_2$MarketName))
[1] "The average lease-up time is 9.67 months in Akron, OH."
Price by Markets
# Effective rent per square feet in Texas
library(dplyr)
library(data.table)
library(ggplot2)
eff_rnt_per_sq_ft_1_by_submarket = merge(info_1, eff_rnt_per_sq_ft_1, by.y = 0, by.x = 'ProjID') %>% select('Submarket', c(31:168)) %>% group_by(Submarket) %>% summarise_all(mean, na.rm = TRUE)
erps_1 <- ggplot(data = melt(eff_rnt_per_sq_ft_1_by_submarket, id.vars = 'Submarket'), aes(x = variable, y = value, group = Submarket)) + geom_line(aes(colour=Submarket, group=Submarket)) + labs(title = 'Effective Rent per Square in Texas by Submarkets', y = 'Rent per Square') + theme_classic() + scale_x_discrete(name = 'Year', breaks = c('Jan-09', 'Jan-10', 'Jan-11', 'Jan-12', 'Jan-13', 'Jan-14', 'Jan-15', 'Jan-16', 'Jan-17', 'Jan-18', 'Jan-19'))
The melt generic in data.table has been passed a tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(eff_rnt_per_sq_ft_1_by_submarket). In the next version, this warning will become an error.
erps_1

In Austin-Round Rock, Texas, submarket Downtown/University has the highest effective rent per square, which is around 50% higher than the average effective rent per sqaure. Also, the effective rent per square in submarket South Austin increases fastest in recent years.
library(forecast)
price_time_series_1 <- ts(as.numeric(apply(eff_rnt_per_sq_ft_1_by_submarket[,c(2:139)], 2, mean)), frequency = 12, start = c(2008, 4))
plot.ts(price_time_series_1)

price_decomp_1 <- decompose(price_time_series_1)
# plot(price_decomp_1$seasonal[10:21], type = 'l', xlab='Months', ylab='Seasonality', main = 'Seasonality of Effective Rent per Sqaure in Texas in Decomposition')
plot(price_decomp_1)

In Austin-Round Rock, Texas, if renting apartments during Christimas, renters can save around $0.02 per square monthly comparing to renting during Summer Break (such as July, August, September). Also, the effective price per square went down during 2008 to 2010, then it went up after 2010, and it went up around 5% yearly.
# Effective rent per square feet in Ohio
eff_rnt_per_sq_ft_2_by_submarket = merge(info_2, eff_rnt_per_sq_ft_2, by.y = 0, by.x = 'ProjID') %>% select('Submarket', c(31:168)) %>% group_by(Submarket) %>% summarise_all(mean, na.rm = TRUE)
erps_2 <- ggplot(data = melt(eff_rnt_per_sq_ft_2_by_submarket, id.vars = 'Submarket'), aes(x = variable, y = value, group = Submarket)) + geom_line(aes(colour=Submarket, group=Submarket)) + labs(title = 'Effective Rent per Square in Ohio by Submarkets', y = 'Rent per Square') + theme_classic() + scale_x_discrete(name = 'Year', breaks = c('Jan-09', 'Jan-10', 'Jan-11', 'Jan-12', 'Jan-13', 'Jan-14', 'Jan-15', 'Jan-16', 'Jan-17', 'Jan-18', 'Jan-19'))
The melt generic in data.table has been passed a tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(eff_rnt_per_sq_ft_2_by_submarket). In the next version, this warning will become an error.
erps_2

In Akron, OH, submarket Kent/Portage County has the highest effective price per square and submarket South Summit County has the lowest effective price per square. Effective price per square in Kent/Portage County is around 10% higher than North Summit County, and effective price per square in North Summit County is also 10% higher than South Summit County. All three counties have similar effective price per square inflation rates from 2008 to 2019.
price_time_series_2 <- ts(as.numeric(apply(eff_rnt_per_sq_ft_2_by_submarket[,c(2:139)], 2, mean)), frequency = 12, start = c(2008, 4))
plot.ts(price_time_series_2)

plot(decompose(price_time_series_2))

In Akron, OH, effective price per square shows similar patterns as in Austin-Round Rock, Texas. Effective price per square went down before 2010 then up after 2010 except the yearly inflation rate is around 3%. It also shows lower effective price per square during Christmas comparing to Summer Break.
Occupancy by Markets
# Occupancy Rate in Texas
occupancy_1_by_submarket = merge(info_1, occupancy_1, by.y = 0, by.x = 'ProjID') %>% select('Submarket', c(31:168)) %>% group_by(Submarket) %>% summarise_all(mean, na.rm = TRUE)
occupancy_1 <- ggplot(data = melt(occupancy_1_by_submarket, id.vars = 'Submarket'), aes(x = variable, y = value, group = Submarket)) + geom_line(aes(colour=Submarket, group=Submarket)) + labs(title = 'Occupancy % in Texas by Submarkets', y = 'Percentage') + theme_classic() + scale_x_discrete(name = 'Year', breaks = c('Jan-09', 'Jan-10', 'Jan-11', 'Jan-12', 'Jan-13', 'Jan-14', 'Jan-15', 'Jan-16', 'Jan-17', 'Jan-18', 'Jan-19'))
The melt generic in data.table has been passed a tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(occupancy_1_by_submarket). In the next version, this warning will become an error.
occupancy_1

In Austin-Round Rock, Texas, East Austin has low occupancy rate during 2008 and Downtown/University has low occupancy rate during 2016. And the average occupancy rate is between 90%-95%.
occupancy_time_series_1 <- ts(as.numeric(apply(occupancy_1_by_submarket[,c(2:139)], 2, mean)), frequency = 12, start = c(2008, 4))
plot.ts(occupancy_time_series_1)

occupancy_decomp_1 <- decompose(occupancy_time_series_1)
plot(occupancy_decomp_1)

In Austin-Round Rock, Texas, the average occupancy rate is lower during Christimas Break comparing to Summer Break. And the average occupancy rate went up from 2009 to 2011, then went down after 2011 until 2018, then went up again after 2018. Average occupancy rate is around 92%.
# Occupancy Rate in Ohio
occupancy_2_by_submarket = merge(info_2, occupancy_2, by.y = 0, by.x = 'ProjID') %>% select('Submarket', c(31:168)) %>% group_by(Submarket) %>% summarise_all(mean, na.rm = TRUE)
occupancy_2 <- ggplot(data = melt(occupancy_2_by_submarket, id.vars = 'Submarket'), aes(x = variable, y = value, group = Submarket)) + geom_line(aes(colour=Submarket, group=Submarket)) + labs(title = 'Occupancy % in Ohio by Submarkets', y = 'Percentage') + theme_classic() + scale_x_discrete(name = 'Year', breaks = c('Jan-09', 'Jan-10', 'Jan-11', 'Jan-12', 'Jan-13', 'Jan-14', 'Jan-15', 'Jan-16', 'Jan-17', 'Jan-18', 'Jan-19'))
The melt generic in data.table has been passed a tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(occupancy_2_by_submarket). In the next version, this warning will become an error.
occupancy_2

In Akron, OH, occupancy rate in South Summit County is generally lower to occupancy rate in Kent/Portage County and North Summit County. And Sounth Summit County has lowest occupancy rate during 2008, which drops to 85%.
occupancy_time_series_2 <- ts(as.numeric(apply(occupancy_2_by_submarket[,c(2:139)], 2, mean)), frequency = 12, start = c(2008, 4))
plot.ts(occupancy_time_series_2)

occupancy_decomp_2 <- decompose(occupancy_time_series_2)
plot(occupancy_decomp_2)

In Akron, OH, the average occupancy rate is also lowest during Christimas Break, but in Summer Break, it is not the highest. It has the highest occupancy rate in June, then drops in July, August, September, and rises again in October. Average occupancy rate fluctuates druing 2008 and 2019, which is lowest in 2010 and highest in 2015. Average occupancy rate is around 95%.
Concession by Markets
# Concession percent in Texas
concession_percent_1_by_submarket = merge(info_1, concession_percent_1, by.y = 0, by.x = 'ProjID') %>% select('Submarket', c(31:168)) %>% group_by(Submarket) %>% summarise_all(mean, na.rm = TRUE)
cp_1 <- ggplot(data = melt(concession_percent_1_by_submarket, id.vars = 'Submarket'), aes(x = variable, y = value, group = Submarket)) + geom_line(aes(colour=Submarket, group=Submarket)) + labs(title = 'Concession % in Texas by Submarkets', y = 'Percentage') + theme_classic() + scale_x_discrete(name = 'Year', breaks = c('Jan-09', 'Jan-10', 'Jan-11', 'Jan-12', 'Jan-13', 'Jan-14', 'Jan-15', 'Jan-16', 'Jan-17', 'Jan-18', 'Jan-19'))
The melt generic in data.table has been passed a tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(concession_percent_1_by_submarket). In the next version, this warning will become an error.
cp_1

In Austin-Round Rock, Texas, submarket Far West Austin provides highest concession percentage during 2010, which is around 15%. And overall concession percentage is higher between 2008 to 2010 comparing to other time periods.
concession_time_series_1 <- ts(as.numeric(apply(concession_percent_1_by_submarket[,c(2:139)], 2, mean)), frequency = 12, start = c(2008, 4))
plot.ts(concession_time_series_1)

concession_decomp_1 <- decompose(concession_time_series_1)
plot(concession_decomp_1)

In Austin-Round Rock, Texas, concession percentage is generally higher in Christmas Break comparing to Summer Break. And average concession percentage is highest in 2010, whcih is around 7%, and generally, it is around 1%.
# Concession percent in Ohio
concession_percent_2_by_submarket = merge(info_2, concession_percent_2, by.y = 0, by.x = 'ProjID') %>% select('Submarket', c(31:168)) %>% group_by(Submarket) %>% summarise_all(mean, na.rm = TRUE)
cp_2 <- ggplot(data = melt(concession_percent_2_by_submarket, id.vars = 'Submarket'), aes(x = variable, y = value, group = Submarket)) + geom_line(aes(colour=Submarket, group=Submarket)) + labs(title = 'Concession % in Ohio by Submarkets', y = 'Percentage') + theme_classic() + scale_x_discrete(name = 'Year', breaks = c('Jan-09', 'Jan-10', 'Jan-11', 'Jan-12', 'Jan-13', 'Jan-14', 'Jan-15', 'Jan-16', 'Jan-17', 'Jan-18', 'Jan-19'))
The melt generic in data.table has been passed a tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(concession_percent_2_by_submarket). In the next version, this warning will become an error.
cp_2

In Akron, OH, the concession percentage is generally higher in South Summit County comparing to the other two counties. Concession percentage is highest in 2010, which is around 8% in South Summit County.
concession_time_series_2 <- ts(as.numeric(apply(concession_percent_2_by_submarket[,c(2:139)], 2, mean)), frequency = 12, start = c(2008, 4))
plot.ts(concession_time_series_2)

concession_decomp_2 <- decompose(concession_time_series_2)
plot(concession_decomp_2)

In Akron, OH, within a year, concession percentage is highest during Christmas Break but lowest in October, and the concession percentage drops consistly from Febrary to October. The average concession percentage is highest in 2010, around 4%, and in general, it is around 1%.
Summary
In high-level summary, markets in both Texas and Ohio are pessimistic in 2008-2010, which result the low effective price per square, low occupancy rate, and high concession percentage. And after 2010, the markets in both Texas and Ohio get better and better, which results increasing effective price per sqaure, decreasing occupancy rates, and decreasing concession percentages. Within a year, markets perform worse in Christmas Break than Summer Break, so there are higher concession percentages in Christmas Break.
In Austin-Round Rock, Texas, Downtown/University is the most expensive submarket, which is around 50% higher in terms of effective price per sqaure. Average effective price per sqaure in Austin-Round Rock, Texas is around $1.5 in September 2019. In Akron, OH, Kent/Portage County is the most expensive submarket, which is around 10% higher in terms of effective price per square. Average effective price per square in Akron, OH is around $1.0 in September, 2019.
The average concession percentage is around 1% in both Texas and Ohio market, and the average occupancy rate is around 92% in Texas and 95% in Ohio.
In this analysis, I implement uniform weights to calcalute averages for simplicity. However, the analysis could be more accurate if we calculate average effective price per square weighted by total squares (Quantity*AreaPerUnit), average occupancy rate weighted by Quantity, and average concession percentage weighted by monthly total asking price of available units in building ((1-Occupancy_rate)*Quantity*asking_rent).
Also, if I have more time, I will analyze management companies in markets. For example, which management companies manage luxury building? Which management companies are the most popular ones in markets? Which management companies have the largest assets? And which management companies have the best grades in markets?
LS0tCnRpdGxlOiAiUHJvcGVydHkgTGVhc2UtVXAgU3VtbWFyeSIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7cn0KbGlicmFyeShyZWFkeGwpCiMgbG9hZCB0aGUgZGF0YQppbmZvXzEgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMS54bHN4Jywgc2hlZXQgPSAnUmVudCcsIHJhbmdlID0gJ0E1OkFEODUxJykKYXNraW5nX3JlbnRfMSA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0ExLnhsc3gnLCBzaGVldCA9ICdSZW50JywgcmFuZ2UgPSAnQUU1OkZMODUxJykKcm93bmFtZXMoYXNraW5nX3JlbnRfMSkgPSBpbmZvXzEkUHJvaklECmVmZmVjdGl2ZV9yZW50XzEgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMS54bHN4Jywgc2hlZXQgPSAnUmVudCcsIHJhbmdlID0gJ0ZNNTpLVDg1MScpCnJvd25hbWVzKGVmZmVjdGl2ZV9yZW50XzEpID0gaW5mb18xJFByb2pJRAplZmZfcm50X3Blcl9zcV9mdF8xID0gcmVhZF9leGNlbChwYXRoID0gJ34vRG9jdW1lbnRzL0pvYiBBcHBsaWNhdGlvbi9VU0FBL01TQTEueGxzeCcsIHNoZWV0ID0gJ1JlbnQnLCByYW5nZSA9ICdLVTU6UUI4NTEnKQpyb3duYW1lcyhlZmZfcm50X3Blcl9zcV9mdF8xKSA9IGluZm9fMSRQcm9qSUQKb2NjdXBhbmN5XzEgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMS54bHN4Jywgc2hlZXQgPSAnT2NjICYgQ29uY2Vzc2lvbicsIHJhbmdlID0gJ0FFNTpGTDg1MScpCnJvd25hbWVzKG9jY3VwYW5jeV8xKSA9IGluZm9fMSRQcm9qSUQKY29uY2Vzc2lvbl92YWx1ZV8xID0gcmVhZF9leGNlbChwYXRoID0gJ34vRG9jdW1lbnRzL0pvYiBBcHBsaWNhdGlvbi9VU0FBL01TQTEueGxzeCcsIHNoZWV0ID0gJ09jYyAmIENvbmNlc3Npb24nLCByYW5nZSA9ICdGTTU6S1Q4NTEnKQpyb3duYW1lcyhjb25jZXNzaW9uX3ZhbHVlXzEpID0gaW5mb18xJFByb2pJRApjb25jZXNzaW9uX3BlcmNlbnRfMSA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0ExLnhsc3gnLCBzaGVldCA9ICdPY2MgJiBDb25jZXNzaW9uJywgcmFuZ2UgPSAnS1U1OlFCODUxJykKcm93bmFtZXMoY29uY2Vzc2lvbl9wZXJjZW50XzEpID0gaW5mb18xJFByb2pJRApwcm9wZXJ0eV9zdWJtYXJrZXRfZ3JhZGVfMSA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0ExLnhsc3gnLCBzaGVldCA9ICdBc3NldCBDbGFzcycsIHJhbmdlID0gJ0FFNTpGTDg1MScpCnJvd25hbWVzKHByb3BlcnR5X3N1Ym1hcmtldF9ncmFkZV8xKSA9IGluZm9fMSRQcm9qSUQKcHJvcGVydHlfbWFya2V0X2dyYWRlXzEgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMS54bHN4Jywgc2hlZXQgPSAnQXNzZXQgQ2xhc3MnLCByYW5nZSA9ICdGTTU6S1Q4NTEnKQpyb3duYW1lcyhwcm9wZXJ0eV9tYXJrZXRfZ3JhZGVfMSkgPSBpbmZvXzEkUHJvaklECnN1Ym1hcmtldF9ncmFkZV8xID0gcmVhZF9leGNlbChwYXRoID0gJ34vRG9jdW1lbnRzL0pvYiBBcHBsaWNhdGlvbi9VU0FBL01TQTEueGxzeCcsIHNoZWV0ID0gJ0Fzc2V0IENsYXNzJywgcmFuZ2UgPSAnS1U1OlFCODUxJykKcm93bmFtZXMoc3VibWFya2V0X2dyYWRlXzEpID0gaW5mb18xJFByb2pJRApwcm9wZXJ0eV9zdGF0dXNfMSA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0ExLnhsc3gnLCBzaGVldCA9ICdQcm9wZXJ0eSBTdGF0dXMnLCByYW5nZSA9ICdBRTU6Rkw4NTEnKQpyb3duYW1lcyhwcm9wZXJ0eV9zdGF0dXNfMSkgPSBpbmZvXzEkUHJvaklECgppbmZvXzIgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMi54bHN4Jywgc2hlZXQgPSAnUmVudCcsIHJhbmdlID0gJ0E1OkFEMTA0JykKYXNraW5nX3JlbnRfMiA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0EyLnhsc3gnLCBzaGVldCA9ICdSZW50JywgcmFuZ2UgPSAnQUU1OkZMMTA0JykKcm93bmFtZXMoYXNraW5nX3JlbnRfMikgPSBpbmZvXzIkUHJvaklECmVmZmVjdGl2ZV9yZW50XzIgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMi54bHN4Jywgc2hlZXQgPSAnUmVudCcsIHJhbmdlID0gJ0ZNNTpLVDEwNCcpCnJvd25hbWVzKGVmZmVjdGl2ZV9yZW50XzIpID0gaW5mb18yJFByb2pJRAplZmZfcm50X3Blcl9zcV9mdF8yID0gcmVhZF9leGNlbChwYXRoID0gJ34vRG9jdW1lbnRzL0pvYiBBcHBsaWNhdGlvbi9VU0FBL01TQTIueGxzeCcsIHNoZWV0ID0gJ1JlbnQnLCByYW5nZSA9ICdLVTU6UUIxMDQnKQpyb3duYW1lcyhlZmZfcm50X3Blcl9zcV9mdF8yKSA9IGluZm9fMiRQcm9qSUQKb2NjdXBhbmN5XzIgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMi54bHN4Jywgc2hlZXQgPSAnT2NjICYgQ29uY2Vzc2lvbicsIHJhbmdlID0gJ0FFNTpGTDEwNCcpCnJvd25hbWVzKG9jY3VwYW5jeV8yKSA9IGluZm9fMiRQcm9qSUQKY29uY2Vzc2lvbl92YWx1ZV8yID0gcmVhZF9leGNlbChwYXRoID0gJ34vRG9jdW1lbnRzL0pvYiBBcHBsaWNhdGlvbi9VU0FBL01TQTIueGxzeCcsIHNoZWV0ID0gJ09jYyAmIENvbmNlc3Npb24nLCByYW5nZSA9ICdGTTU6S1QxMDQnKQpyb3duYW1lcyhjb25jZXNzaW9uX3ZhbHVlXzIpID0gaW5mb18yJFByb2pJRApjb25jZXNzaW9uX3BlcmNlbnRfMiA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0EyLnhsc3gnLCBzaGVldCA9ICdPY2MgJiBDb25jZXNzaW9uJywgcmFuZ2UgPSAnS1U1OlFCMTA0JykKcm93bmFtZXMoY29uY2Vzc2lvbl9wZXJjZW50XzIpID0gaW5mb18yJFByb2pJRApwcm9wZXJ0eV9zdWJtYXJrZXRfZ3JhZGVfMiA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0EyLnhsc3gnLCBzaGVldCA9ICdBc3NldCBDbGFzcycsIHJhbmdlID0gJ0FFNTpGTDEwNCcpCnJvd25hbWVzKHByb3BlcnR5X3N1Ym1hcmtldF9ncmFkZV8yKSA9IGluZm9fMiRQcm9qSUQKcHJvcGVydHlfbWFya2V0X2dyYWRlXzIgPSByZWFkX2V4Y2VsKHBhdGggPSAnfi9Eb2N1bWVudHMvSm9iIEFwcGxpY2F0aW9uL1VTQUEvTVNBMi54bHN4Jywgc2hlZXQgPSAnQXNzZXQgQ2xhc3MnLCByYW5nZSA9ICdGTTU6S1QxMDQnKQpyb3duYW1lcyhwcm9wZXJ0eV9tYXJrZXRfZ3JhZGVfMikgPSBpbmZvXzIkUHJvaklECnN1Ym1hcmtldF9ncmFkZV8yID0gcmVhZF9leGNlbChwYXRoID0gJ34vRG9jdW1lbnRzL0pvYiBBcHBsaWNhdGlvbi9VU0FBL01TQTIueGxzeCcsIHNoZWV0ID0gJ0Fzc2V0IENsYXNzJywgcmFuZ2UgPSAnS1U1OlFCMTA0JykKcm93bmFtZXMoc3VibWFya2V0X2dyYWRlXzIpID0gaW5mb18yJFByb2pJRApwcm9wZXJ0eV9zdGF0dXNfMiA9IHJlYWRfZXhjZWwocGF0aCA9ICd+L0RvY3VtZW50cy9Kb2IgQXBwbGljYXRpb24vVVNBQS9NU0EyLnhsc3gnLCBzaGVldCA9ICdQcm9wZXJ0eSBTdGF0dXMnLCByYW5nZSA9ICdBRTU6RkwxMDQnKQpyb3duYW1lcyhwcm9wZXJ0eV9zdGF0dXNfMikgPSBpbmZvXzIkUHJvaklECmBgYAoKIyMgTnVtYmVyIG9mIFByb3BlcnRpZXMgRGVsaXZlcmVkIFNpbmNlIEFwcmlsIDIwMDggYnkgTWFya2V0cwoKYGBge3J9CiMgTnVtYmVyIG9mIHByb3BlcnRpZXMgZGVsaXZlcmVkIHNpbmNlIEFwcmlsIDIwMDgKc3ByaW50ZignVGhlcmUgYXJlICVpIHByb3BlcnRpZXMgYXJlIGRlbGl2ZXJlZCBzaW5jZSBBcHJpbCAyMDA4IGluICVzLicsIHN1bShhcHBseShwcm9wZXJ0eV9zdGF0dXNfMSwgMSwgZnVuY3Rpb24oeCkgbmEub21pdCh4KVsxXSkgJWluJSBjKCdMVScsICdVQy9MVScpKSwgdW5pcXVlKGluZm9fMSRNYXJrZXROYW1lKSkKc3ByaW50ZignVGhlcmUgYXJlICVpIHByb3BlcnRpZXMgYXJlIGRlbGl2ZXJlZCBzaW5jZSBBcHJpbCAyMDA4IGluICVzLicsIHN1bShhcHBseShwcm9wZXJ0eV9zdGF0dXNfMiwgMSwgZnVuY3Rpb24oeCkgbmEub21pdCh4KVsxXSkgJWluJSBjKCdMVScsICdVQy9MVScpKSwgdW5pcXVlKGluZm9fMiRNYXJrZXROYW1lKSkKYGBgCgojIyBBdmVyYWdlIExlYXNlLVVwIFRpbWUgYnkgTWFya2V0cwoKYGBge3J9CiMgQXZlcmFnZSBsZWFzZS11cCB0aW1lCmRlbGl2ZXJlZF8xIDwtIGluZm9fMSRQcm9qSURbYXBwbHkocHJvcGVydHlfc3RhdHVzXzEsIDEsIGZ1bmN0aW9uKHgpIG5hLm9taXQoeClbMV0pICVpbiUgYygnTFUnLCAnVUMvTFUnKV0KZGVsaXZlcmVkXzIgPC0gaW5mb18yJFByb2pJRFthcHBseShwcm9wZXJ0eV9zdGF0dXNfMiwgMSwgZnVuY3Rpb24oeCkgbmEub21pdCh4KVsxXSkgJWluJSBjKCdMVScsICdVQy9MVScpXQoKbGVhc2VfdXBfdGltZSA8LSBmdW5jdGlvbihsKXsKICBpIDwtIDAKICB3aGlsZShsW1tpKzFdXSA8IDAuOSl7CiAgICBpID0gaSArIDEKICAgIGlmIChpID09IGxlbmd0aChsKSkgewogICAgICBicmVhawogICAgfQogIH0KICByZXR1cm4oaSkKfQoKbGVhc2VfdXBfdGltZV8xIDwtIGFzLm51bWVyaWMobGFwcGx5KGFwcGx5KG9jY3VwYW5jeV8xW3Jvd25hbWVzKG9jY3VwYW5jeV8xKSAlaW4lIGRlbGl2ZXJlZF8xLF0sIDEsIGZ1bmN0aW9uKHgpIG5hLm9taXQoeCkpLCBsZWFzZV91cF90aW1lKSkKbGVhc2VfdXBfdGltZV8yIDwtIGFzLm51bWVyaWMobGFwcGx5KGFwcGx5KG9jY3VwYW5jeV8yW3Jvd25hbWVzKG9jY3VwYW5jeV8yKSAlaW4lIGRlbGl2ZXJlZF8yLF0sIDEsIGZ1bmN0aW9uKHgpIG5hLm9taXQoeCkpLCBsZWFzZV91cF90aW1lKSkKCnNwcmludGYoJ1RoZSBhdmVyYWdlIGxlYXNlLXVwIHRpbWUgaXMgJS4yZiBtb250aHMgaW4gJXMuJywgbWVhbihsZWFzZV91cF90aW1lXzEpLCB1bmlxdWUoaW5mb18xJE1hcmtldE5hbWUpKQpzcHJpbnRmKCdUaGUgYXZlcmFnZSBsZWFzZS11cCB0aW1lIGlzICUuMmYgbW9udGhzIGluICVzLicsIG1lYW4obGVhc2VfdXBfdGltZV8yKSwgdW5pcXVlKGluZm9fMiRNYXJrZXROYW1lKSkKYGBgCgojIyBQcmljZSBieSBNYXJrZXRzCgpgYGB7cn0KIyBFZmZlY3RpdmUgcmVudCBwZXIgc3F1YXJlIGZlZXQgaW4gVGV4YXMKbGlicmFyeShkcGx5cikKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCgplZmZfcm50X3Blcl9zcV9mdF8xX2J5X3N1Ym1hcmtldCA9IG1lcmdlKGluZm9fMSwgZWZmX3JudF9wZXJfc3FfZnRfMSwgYnkueSA9IDAsIGJ5LnggPSAnUHJvaklEJykgJT4lIHNlbGVjdCgnU3VibWFya2V0JywgYygzMToxNjgpKSAlPiUgZ3JvdXBfYnkoU3VibWFya2V0KSAlPiUgc3VtbWFyaXNlX2FsbChtZWFuLCBuYS5ybSA9IFRSVUUpCmVycHNfMSA8LSBnZ3Bsb3QoZGF0YSA9IG1lbHQoZWZmX3JudF9wZXJfc3FfZnRfMV9ieV9zdWJtYXJrZXQsIGlkLnZhcnMgPSAnU3VibWFya2V0JyksIGFlcyh4ID0gdmFyaWFibGUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBTdWJtYXJrZXQpKSArIGdlb21fbGluZShhZXMoY29sb3VyPVN1Ym1hcmtldCwgZ3JvdXA9U3VibWFya2V0KSkgKyBsYWJzKHRpdGxlID0gJ0VmZmVjdGl2ZSBSZW50IHBlciBTcXVhcmUgaW4gVGV4YXMgYnkgU3VibWFya2V0cycsIHkgPSAnUmVudCBwZXIgU3F1YXJlJykgKyB0aGVtZV9jbGFzc2ljKCkgKyBzY2FsZV94X2Rpc2NyZXRlKG5hbWUgPSAnWWVhcicsIGJyZWFrcyA9IGMoJ0phbi0wOScsICdKYW4tMTAnLCAnSmFuLTExJywgJ0phbi0xMicsICdKYW4tMTMnLCAnSmFuLTE0JywgJ0phbi0xNScsICdKYW4tMTYnLCAnSmFuLTE3JywgJ0phbi0xOCcsICdKYW4tMTknKSkKZXJwc18xCmBgYAoKSW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLCBzdWJtYXJrZXQgRG93bnRvd24vVW5pdmVyc2l0eSBoYXMgdGhlIGhpZ2hlc3QgZWZmZWN0aXZlIHJlbnQgcGVyIHNxdWFyZSwgd2hpY2ggaXMgYXJvdW5kIDUwJSBoaWdoZXIgdGhhbiB0aGUgYXZlcmFnZSBlZmZlY3RpdmUgcmVudCBwZXIgc3FhdXJlLiBBbHNvLCB0aGUgZWZmZWN0aXZlIHJlbnQgcGVyIHNxdWFyZSBpbiBzdWJtYXJrZXQgU291dGggQXVzdGluIGluY3JlYXNlcyBmYXN0ZXN0IGluIHJlY2VudCB5ZWFycy4gCgpgYGB7cn0KbGlicmFyeShmb3JlY2FzdCkKcHJpY2VfdGltZV9zZXJpZXNfMSA8LSB0cyhhcy5udW1lcmljKGFwcGx5KGVmZl9ybnRfcGVyX3NxX2Z0XzFfYnlfc3VibWFya2V0WyxjKDI6MTM5KV0sIDIsIG1lYW4pKSwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYygyMDA4LCA0KSkKcGxvdC50cyhwcmljZV90aW1lX3Nlcmllc18xKQpwcmljZV9kZWNvbXBfMSA8LSBkZWNvbXBvc2UocHJpY2VfdGltZV9zZXJpZXNfMSkKIyBwbG90KHByaWNlX2RlY29tcF8xJHNlYXNvbmFsWzEwOjIxXSwgdHlwZSA9ICdsJywgeGxhYj0nTW9udGhzJywgeWxhYj0nU2Vhc29uYWxpdHknLCBtYWluID0gJ1NlYXNvbmFsaXR5IG9mIEVmZmVjdGl2ZSBSZW50IHBlciBTcWF1cmUgaW4gVGV4YXMgaW4gRGVjb21wb3NpdGlvbicpCnBsb3QocHJpY2VfZGVjb21wXzEpCmBgYAoKSW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLCBpZiByZW50aW5nIGFwYXJ0bWVudHMgZHVyaW5nIENocmlzdGltYXMsIHJlbnRlcnMgY2FuIHNhdmUgYXJvdW5kICQwLjAyIHBlciBzcXVhcmUgbW9udGhseSBjb21wYXJpbmcgdG8gcmVudGluZyBkdXJpbmcgU3VtbWVyIEJyZWFrIChzdWNoIGFzIEp1bHksIEF1Z3VzdCwgU2VwdGVtYmVyKS4gQWxzbywgdGhlIGVmZmVjdGl2ZSBwcmljZSBwZXIgc3F1YXJlIHdlbnQgZG93biBkdXJpbmcgMjAwOCB0byAyMDEwLCB0aGVuIGl0IHdlbnQgdXAgYWZ0ZXIgMjAxMCwgYW5kIGl0IHdlbnQgdXAgYXJvdW5kIDUlIHllYXJseS4KCgpgYGB7cn0KIyBFZmZlY3RpdmUgcmVudCBwZXIgc3F1YXJlIGZlZXQgaW4gT2hpbwplZmZfcm50X3Blcl9zcV9mdF8yX2J5X3N1Ym1hcmtldCA9IG1lcmdlKGluZm9fMiwgZWZmX3JudF9wZXJfc3FfZnRfMiwgYnkueSA9IDAsIGJ5LnggPSAnUHJvaklEJykgJT4lIHNlbGVjdCgnU3VibWFya2V0JywgYygzMToxNjgpKSAlPiUgZ3JvdXBfYnkoU3VibWFya2V0KSAlPiUgc3VtbWFyaXNlX2FsbChtZWFuLCBuYS5ybSA9IFRSVUUpCmVycHNfMiA8LSBnZ3Bsb3QoZGF0YSA9IG1lbHQoZWZmX3JudF9wZXJfc3FfZnRfMl9ieV9zdWJtYXJrZXQsIGlkLnZhcnMgPSAnU3VibWFya2V0JyksIGFlcyh4ID0gdmFyaWFibGUsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBTdWJtYXJrZXQpKSArIGdlb21fbGluZShhZXMoY29sb3VyPVN1Ym1hcmtldCwgZ3JvdXA9U3VibWFya2V0KSkgKyBsYWJzKHRpdGxlID0gJ0VmZmVjdGl2ZSBSZW50IHBlciBTcXVhcmUgaW4gT2hpbyBieSBTdWJtYXJrZXRzJywgeSA9ICdSZW50IHBlciBTcXVhcmUnKSArIHRoZW1lX2NsYXNzaWMoKSArIHNjYWxlX3hfZGlzY3JldGUobmFtZSA9ICdZZWFyJywgYnJlYWtzID0gYygnSmFuLTA5JywgJ0phbi0xMCcsICdKYW4tMTEnLCAnSmFuLTEyJywgJ0phbi0xMycsICdKYW4tMTQnLCAnSmFuLTE1JywgJ0phbi0xNicsICdKYW4tMTcnLCAnSmFuLTE4JywgJ0phbi0xOScpKQplcnBzXzIKYGBgCgpJbiBBa3JvbiwgT0gsIHN1Ym1hcmtldCBLZW50L1BvcnRhZ2UgQ291bnR5IGhhcyB0aGUgaGlnaGVzdCBlZmZlY3RpdmUgcHJpY2UgcGVyIHNxdWFyZSBhbmQgc3VibWFya2V0IFNvdXRoIFN1bW1pdCBDb3VudHkgaGFzIHRoZSBsb3dlc3QgZWZmZWN0aXZlIHByaWNlIHBlciBzcXVhcmUuIEVmZmVjdGl2ZSBwcmljZSBwZXIgc3F1YXJlIGluIEtlbnQvUG9ydGFnZSBDb3VudHkgaXMgYXJvdW5kIDEwJSBoaWdoZXIgdGhhbiBOb3J0aCBTdW1taXQgQ291bnR5LCBhbmQgZWZmZWN0aXZlIHByaWNlIHBlciBzcXVhcmUgaW4gTm9ydGggU3VtbWl0IENvdW50eSBpcyBhbHNvIDEwJSBoaWdoZXIgdGhhbiBTb3V0aCBTdW1taXQgQ291bnR5LiBBbGwgdGhyZWUgY291bnRpZXMgaGF2ZSBzaW1pbGFyIGVmZmVjdGl2ZSBwcmljZSBwZXIgc3F1YXJlIGluZmxhdGlvbiByYXRlcyBmcm9tIDIwMDggdG8gMjAxOS4KCgpgYGB7cn0KcHJpY2VfdGltZV9zZXJpZXNfMiA8LSB0cyhhcy5udW1lcmljKGFwcGx5KGVmZl9ybnRfcGVyX3NxX2Z0XzJfYnlfc3VibWFya2V0WyxjKDI6MTM5KV0sIDIsIG1lYW4pKSwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYygyMDA4LCA0KSkKcGxvdC50cyhwcmljZV90aW1lX3Nlcmllc18yKQpwbG90KGRlY29tcG9zZShwcmljZV90aW1lX3Nlcmllc18yKSkKYGBgCgpJbiBBa3JvbiwgT0gsIGVmZmVjdGl2ZSBwcmljZSBwZXIgc3F1YXJlIHNob3dzIHNpbWlsYXIgcGF0dGVybnMgYXMgaW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLiBFZmZlY3RpdmUgcHJpY2UgcGVyIHNxdWFyZSB3ZW50IGRvd24gYmVmb3JlIDIwMTAgdGhlbiB1cCBhZnRlciAyMDEwIGV4Y2VwdCB0aGUgeWVhcmx5IGluZmxhdGlvbiByYXRlIGlzIGFyb3VuZCAzJS4gSXQgYWxzbyBzaG93cyBsb3dlciBlZmZlY3RpdmUgcHJpY2UgcGVyIHNxdWFyZSBkdXJpbmcgQ2hyaXN0bWFzIGNvbXBhcmluZyB0byBTdW1tZXIgQnJlYWsuCgojIE9jY3VwYW5jeSBieSBNYXJrZXRzCgpgYGB7cn0KIyBPY2N1cGFuY3kgUmF0ZSBpbiBUZXhhcwpvY2N1cGFuY3lfMV9ieV9zdWJtYXJrZXQgPSBtZXJnZShpbmZvXzEsIG9jY3VwYW5jeV8xLCBieS55ID0gMCwgYnkueCA9ICdQcm9qSUQnKSAlPiUgc2VsZWN0KCdTdWJtYXJrZXQnLCBjKDMxOjE2OCkpICU+JSBncm91cF9ieShTdWJtYXJrZXQpICU+JSBzdW1tYXJpc2VfYWxsKG1lYW4sIG5hLnJtID0gVFJVRSkKb2NjdXBhbmN5XzEgPC0gZ2dwbG90KGRhdGEgPSBtZWx0KG9jY3VwYW5jeV8xX2J5X3N1Ym1hcmtldCwgaWQudmFycyA9ICdTdWJtYXJrZXQnKSwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IHZhbHVlLCBncm91cCA9IFN1Ym1hcmtldCkpICsgZ2VvbV9saW5lKGFlcyhjb2xvdXI9U3VibWFya2V0LCBncm91cD1TdWJtYXJrZXQpKSArIGxhYnModGl0bGUgPSAnT2NjdXBhbmN5ICUgaW4gVGV4YXMgYnkgU3VibWFya2V0cycsIHkgPSAnUGVyY2VudGFnZScpICsgdGhlbWVfY2xhc3NpYygpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gJ1llYXInLCBicmVha3MgPSBjKCdKYW4tMDknLCAnSmFuLTEwJywgJ0phbi0xMScsICdKYW4tMTInLCAnSmFuLTEzJywgJ0phbi0xNCcsICdKYW4tMTUnLCAnSmFuLTE2JywgJ0phbi0xNycsICdKYW4tMTgnLCAnSmFuLTE5JykpCm9jY3VwYW5jeV8xCmBgYAoKSW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLCBFYXN0IEF1c3RpbiBoYXMgbG93IG9jY3VwYW5jeSByYXRlIGR1cmluZyAyMDA4IGFuZCBEb3dudG93bi9Vbml2ZXJzaXR5IGhhcyBsb3cgb2NjdXBhbmN5IHJhdGUgZHVyaW5nIDIwMTYuIEFuZCB0aGUgYXZlcmFnZSBvY2N1cGFuY3kgcmF0ZSBpcyBiZXR3ZWVuIDkwJS05NSUuIAoKYGBge3J9Cm9jY3VwYW5jeV90aW1lX3Nlcmllc18xIDwtIHRzKGFzLm51bWVyaWMoYXBwbHkob2NjdXBhbmN5XzFfYnlfc3VibWFya2V0WyxjKDI6MTM5KV0sIDIsIG1lYW4pKSwgZnJlcXVlbmN5ID0gMTIsIHN0YXJ0ID0gYygyMDA4LCA0KSkKcGxvdC50cyhvY2N1cGFuY3lfdGltZV9zZXJpZXNfMSkKb2NjdXBhbmN5X2RlY29tcF8xIDwtIGRlY29tcG9zZShvY2N1cGFuY3lfdGltZV9zZXJpZXNfMSkKcGxvdChvY2N1cGFuY3lfZGVjb21wXzEpCmBgYAoKSW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLCB0aGUgYXZlcmFnZSBvY2N1cGFuY3kgcmF0ZSBpcyBsb3dlciBkdXJpbmcgQ2hyaXN0aW1hcyBCcmVhayBjb21wYXJpbmcgdG8gU3VtbWVyIEJyZWFrLiBBbmQgdGhlIGF2ZXJhZ2Ugb2NjdXBhbmN5IHJhdGUgd2VudCB1cCBmcm9tIDIwMDkgdG8gMjAxMSwgdGhlbiB3ZW50IGRvd24gYWZ0ZXIgMjAxMSB1bnRpbCAyMDE4LCB0aGVuIHdlbnQgdXAgYWdhaW4gYWZ0ZXIgMjAxOC4gQXZlcmFnZSBvY2N1cGFuY3kgcmF0ZSBpcyBhcm91bmQgOTIlLgoKYGBge3J9CiMgT2NjdXBhbmN5IFJhdGUgaW4gT2hpbwpvY2N1cGFuY3lfMl9ieV9zdWJtYXJrZXQgPSBtZXJnZShpbmZvXzIsIG9jY3VwYW5jeV8yLCBieS55ID0gMCwgYnkueCA9ICdQcm9qSUQnKSAlPiUgc2VsZWN0KCdTdWJtYXJrZXQnLCBjKDMxOjE2OCkpICU+JSBncm91cF9ieShTdWJtYXJrZXQpICU+JSBzdW1tYXJpc2VfYWxsKG1lYW4sIG5hLnJtID0gVFJVRSkKb2NjdXBhbmN5XzIgPC0gZ2dwbG90KGRhdGEgPSBtZWx0KG9jY3VwYW5jeV8yX2J5X3N1Ym1hcmtldCwgaWQudmFycyA9ICdTdWJtYXJrZXQnKSwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IHZhbHVlLCBncm91cCA9IFN1Ym1hcmtldCkpICsgZ2VvbV9saW5lKGFlcyhjb2xvdXI9U3VibWFya2V0LCBncm91cD1TdWJtYXJrZXQpKSArIGxhYnModGl0bGUgPSAnT2NjdXBhbmN5ICUgaW4gT2hpbyBieSBTdWJtYXJrZXRzJywgeSA9ICdQZXJjZW50YWdlJykgKyB0aGVtZV9jbGFzc2ljKCkgKyBzY2FsZV94X2Rpc2NyZXRlKG5hbWUgPSAnWWVhcicsIGJyZWFrcyA9IGMoJ0phbi0wOScsICdKYW4tMTAnLCAnSmFuLTExJywgJ0phbi0xMicsICdKYW4tMTMnLCAnSmFuLTE0JywgJ0phbi0xNScsICdKYW4tMTYnLCAnSmFuLTE3JywgJ0phbi0xOCcsICdKYW4tMTknKSkKb2NjdXBhbmN5XzIKYGBgCgpJbiBBa3JvbiwgT0gsIG9jY3VwYW5jeSByYXRlIGluIFNvdXRoIFN1bW1pdCBDb3VudHkgaXMgZ2VuZXJhbGx5IGxvd2VyIHRvIG9jY3VwYW5jeSByYXRlIGluIEtlbnQvUG9ydGFnZSBDb3VudHkgYW5kIE5vcnRoIFN1bW1pdCBDb3VudHkuIEFuZCBTb3VudGggU3VtbWl0IENvdW50eSBoYXMgbG93ZXN0IG9jY3VwYW5jeSByYXRlIGR1cmluZyAyMDA4LCB3aGljaCBkcm9wcyB0byA4NSUuCgpgYGB7cn0Kb2NjdXBhbmN5X3RpbWVfc2VyaWVzXzIgPC0gdHMoYXMubnVtZXJpYyhhcHBseShvY2N1cGFuY3lfMl9ieV9zdWJtYXJrZXRbLGMoMjoxMzkpXSwgMiwgbWVhbikpLCBmcmVxdWVuY3kgPSAxMiwgc3RhcnQgPSBjKDIwMDgsIDQpKQpwbG90LnRzKG9jY3VwYW5jeV90aW1lX3Nlcmllc18yKQpvY2N1cGFuY3lfZGVjb21wXzIgPC0gZGVjb21wb3NlKG9jY3VwYW5jeV90aW1lX3Nlcmllc18yKQpwbG90KG9jY3VwYW5jeV9kZWNvbXBfMikKYGBgCgpJbiBBa3JvbiwgT0gsIHRoZSBhdmVyYWdlIG9jY3VwYW5jeSByYXRlIGlzIGFsc28gbG93ZXN0IGR1cmluZyBDaHJpc3RpbWFzIEJyZWFrLCBidXQgaW4gU3VtbWVyIEJyZWFrLCBpdCBpcyBub3QgdGhlIGhpZ2hlc3QuIEl0IGhhcyB0aGUgaGlnaGVzdCBvY2N1cGFuY3kgcmF0ZSBpbiBKdW5lLCB0aGVuIGRyb3BzIGluIEp1bHksIEF1Z3VzdCwgU2VwdGVtYmVyLCBhbmQgcmlzZXMgYWdhaW4gaW4gT2N0b2Jlci4gQXZlcmFnZSBvY2N1cGFuY3kgcmF0ZSBmbHVjdHVhdGVzIGRydWluZyAyMDA4IGFuZCAyMDE5LCB3aGljaCBpcyBsb3dlc3QgaW4gMjAxMCBhbmQgaGlnaGVzdCBpbiAyMDE1LiBBdmVyYWdlIG9jY3VwYW5jeSByYXRlIGlzIGFyb3VuZCA5NSUuCgojIyBDb25jZXNzaW9uIGJ5IE1hcmtldHMKCmBgYHtyfQojIENvbmNlc3Npb24gcGVyY2VudCBpbiBUZXhhcwpjb25jZXNzaW9uX3BlcmNlbnRfMV9ieV9zdWJtYXJrZXQgPSBtZXJnZShpbmZvXzEsIGNvbmNlc3Npb25fcGVyY2VudF8xLCBieS55ID0gMCwgYnkueCA9ICdQcm9qSUQnKSAlPiUgc2VsZWN0KCdTdWJtYXJrZXQnLCBjKDMxOjE2OCkpICU+JSBncm91cF9ieShTdWJtYXJrZXQpICU+JSBzdW1tYXJpc2VfYWxsKG1lYW4sIG5hLnJtID0gVFJVRSkKY3BfMSA8LSBnZ3Bsb3QoZGF0YSA9IG1lbHQoY29uY2Vzc2lvbl9wZXJjZW50XzFfYnlfc3VibWFya2V0LCBpZC52YXJzID0gJ1N1Ym1hcmtldCcpLCBhZXMoeCA9IHZhcmlhYmxlLCB5ID0gdmFsdWUsIGdyb3VwID0gU3VibWFya2V0KSkgKyBnZW9tX2xpbmUoYWVzKGNvbG91cj1TdWJtYXJrZXQsIGdyb3VwPVN1Ym1hcmtldCkpICsgbGFicyh0aXRsZSA9ICdDb25jZXNzaW9uICUgaW4gVGV4YXMgYnkgU3VibWFya2V0cycsIHkgPSAnUGVyY2VudGFnZScpICsgdGhlbWVfY2xhc3NpYygpICsgc2NhbGVfeF9kaXNjcmV0ZShuYW1lID0gJ1llYXInLCBicmVha3MgPSBjKCdKYW4tMDknLCAnSmFuLTEwJywgJ0phbi0xMScsICdKYW4tMTInLCAnSmFuLTEzJywgJ0phbi0xNCcsICdKYW4tMTUnLCAnSmFuLTE2JywgJ0phbi0xNycsICdKYW4tMTgnLCAnSmFuLTE5JykpCmNwXzEKYGBgCgpJbiBBdXN0aW4tUm91bmQgUm9jaywgVGV4YXMsIHN1Ym1hcmtldCBGYXIgV2VzdCBBdXN0aW4gcHJvdmlkZXMgaGlnaGVzdCBjb25jZXNzaW9uIHBlcmNlbnRhZ2UgZHVyaW5nIDIwMTAsIHdoaWNoIGlzIGFyb3VuZCAxNSUuIEFuZCBvdmVyYWxsIGNvbmNlc3Npb24gcGVyY2VudGFnZSBpcyBoaWdoZXIgYmV0d2VlbiAyMDA4IHRvIDIwMTAgY29tcGFyaW5nIHRvIG90aGVyIHRpbWUgcGVyaW9kcy4KCmBgYHtyfQpjb25jZXNzaW9uX3RpbWVfc2VyaWVzXzEgPC0gdHMoYXMubnVtZXJpYyhhcHBseShjb25jZXNzaW9uX3BlcmNlbnRfMV9ieV9zdWJtYXJrZXRbLGMoMjoxMzkpXSwgMiwgbWVhbikpLCBmcmVxdWVuY3kgPSAxMiwgc3RhcnQgPSBjKDIwMDgsIDQpKQpwbG90LnRzKGNvbmNlc3Npb25fdGltZV9zZXJpZXNfMSkKY29uY2Vzc2lvbl9kZWNvbXBfMSA8LSBkZWNvbXBvc2UoY29uY2Vzc2lvbl90aW1lX3Nlcmllc18xKQpwbG90KGNvbmNlc3Npb25fZGVjb21wXzEpCmBgYAoKSW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLCBjb25jZXNzaW9uIHBlcmNlbnRhZ2UgaXMgZ2VuZXJhbGx5IGhpZ2hlciBpbiBDaHJpc3RtYXMgQnJlYWsgY29tcGFyaW5nIHRvIFN1bW1lciBCcmVhay4gQW5kIGF2ZXJhZ2UgY29uY2Vzc2lvbiBwZXJjZW50YWdlIGlzIGhpZ2hlc3QgaW4gMjAxMCwgd2hjaWggaXMgYXJvdW5kIDclLCBhbmQgZ2VuZXJhbGx5LCBpdCBpcyBhcm91bmQgMSUuCgpgYGB7cn0KIyBDb25jZXNzaW9uIHBlcmNlbnQgaW4gT2hpbwpjb25jZXNzaW9uX3BlcmNlbnRfMl9ieV9zdWJtYXJrZXQgPSBtZXJnZShpbmZvXzIsIGNvbmNlc3Npb25fcGVyY2VudF8yLCBieS55ID0gMCwgYnkueCA9ICdQcm9qSUQnKSAlPiUgc2VsZWN0KCdTdWJtYXJrZXQnLCBjKDMxOjE2OCkpICU+JSBncm91cF9ieShTdWJtYXJrZXQpICU+JSBzdW1tYXJpc2VfYWxsKG1lYW4sIG5hLnJtID0gVFJVRSkKY3BfMiA8LSBnZ3Bsb3QoZGF0YSA9IG1lbHQoY29uY2Vzc2lvbl9wZXJjZW50XzJfYnlfc3VibWFya2V0LCBpZC52YXJzID0gJ1N1Ym1hcmtldCcpLCBhZXMoeCA9IHZhcmlhYmxlLCB5ID0gdmFsdWUsIGdyb3VwID0gU3VibWFya2V0KSkgKyBnZW9tX2xpbmUoYWVzKGNvbG91cj1TdWJtYXJrZXQsIGdyb3VwPVN1Ym1hcmtldCkpICsgbGFicyh0aXRsZSA9ICdDb25jZXNzaW9uICUgaW4gT2hpbyBieSBTdWJtYXJrZXRzJywgeSA9ICdQZXJjZW50YWdlJykgKyB0aGVtZV9jbGFzc2ljKCkgKyBzY2FsZV94X2Rpc2NyZXRlKG5hbWUgPSAnWWVhcicsIGJyZWFrcyA9IGMoJ0phbi0wOScsICdKYW4tMTAnLCAnSmFuLTExJywgJ0phbi0xMicsICdKYW4tMTMnLCAnSmFuLTE0JywgJ0phbi0xNScsICdKYW4tMTYnLCAnSmFuLTE3JywgJ0phbi0xOCcsICdKYW4tMTknKSkKY3BfMgpgYGAKCkluIEFrcm9uLCBPSCwgdGhlIGNvbmNlc3Npb24gcGVyY2VudGFnZSBpcyBnZW5lcmFsbHkgaGlnaGVyIGluIFNvdXRoIFN1bW1pdCBDb3VudHkgY29tcGFyaW5nIHRvIHRoZSBvdGhlciB0d28gY291bnRpZXMuIENvbmNlc3Npb24gcGVyY2VudGFnZSBpcyBoaWdoZXN0IGluIDIwMTAsIHdoaWNoIGlzIGFyb3VuZCA4JSBpbiBTb3V0aCBTdW1taXQgQ291bnR5LgoKYGBge3J9CmNvbmNlc3Npb25fdGltZV9zZXJpZXNfMiA8LSB0cyhhcy5udW1lcmljKGFwcGx5KGNvbmNlc3Npb25fcGVyY2VudF8yX2J5X3N1Ym1hcmtldFssYygyOjEzOSldLCAyLCBtZWFuKSksIGZyZXF1ZW5jeSA9IDEyLCBzdGFydCA9IGMoMjAwOCwgNCkpCnBsb3QudHMoY29uY2Vzc2lvbl90aW1lX3Nlcmllc18yKQpjb25jZXNzaW9uX2RlY29tcF8yIDwtIGRlY29tcG9zZShjb25jZXNzaW9uX3RpbWVfc2VyaWVzXzIpCnBsb3QoY29uY2Vzc2lvbl9kZWNvbXBfMikKYGBgCgpJbiBBa3JvbiwgT0gsIHdpdGhpbiBhIHllYXIsIGNvbmNlc3Npb24gcGVyY2VudGFnZSBpcyBoaWdoZXN0IGR1cmluZyBDaHJpc3RtYXMgQnJlYWsgYnV0IGxvd2VzdCBpbiBPY3RvYmVyLCBhbmQgdGhlIGNvbmNlc3Npb24gcGVyY2VudGFnZSBkcm9wcyBjb25zaXN0bHkgZnJvbSBGZWJyYXJ5IHRvIE9jdG9iZXIuIFRoZSBhdmVyYWdlIGNvbmNlc3Npb24gcGVyY2VudGFnZSBpcyBoaWdoZXN0IGluIDIwMTAsIGFyb3VuZCA0JSwgYW5kIGluIGdlbmVyYWwsIGl0IGlzIGFyb3VuZCAxJS4KCiMjIFN1bW1hcnkKCkluIGhpZ2gtbGV2ZWwgc3VtbWFyeSwgbWFya2V0cyBpbiBib3RoIFRleGFzIGFuZCBPaGlvIGFyZSBwZXNzaW1pc3RpYyBpbiAyMDA4LTIwMTAsIHdoaWNoIHJlc3VsdCB0aGUgbG93IGVmZmVjdGl2ZSBwcmljZSBwZXIgc3F1YXJlLCBsb3cgb2NjdXBhbmN5IHJhdGUsIGFuZCBoaWdoIGNvbmNlc3Npb24gcGVyY2VudGFnZS4gQW5kIGFmdGVyIDIwMTAsIHRoZSBtYXJrZXRzIGluIGJvdGggVGV4YXMgYW5kIE9oaW8gZ2V0IGJldHRlciBhbmQgYmV0dGVyLCB3aGljaCByZXN1bHRzIGluY3JlYXNpbmcgZWZmZWN0aXZlIHByaWNlIHBlciBzcWF1cmUsIGRlY3JlYXNpbmcgb2NjdXBhbmN5IHJhdGVzLCBhbmQgZGVjcmVhc2luZyBjb25jZXNzaW9uIHBlcmNlbnRhZ2VzLiBXaXRoaW4gYSB5ZWFyLCBtYXJrZXRzIHBlcmZvcm0gd29yc2UgaW4gQ2hyaXN0bWFzIEJyZWFrIHRoYW4gU3VtbWVyIEJyZWFrLCBzbyB0aGVyZSBhcmUgaGlnaGVyIGNvbmNlc3Npb24gcGVyY2VudGFnZXMgaW4gQ2hyaXN0bWFzIEJyZWFrLgoKSW4gQXVzdGluLVJvdW5kIFJvY2ssIFRleGFzLCBEb3dudG93bi9Vbml2ZXJzaXR5IGlzIHRoZSBtb3N0IGV4cGVuc2l2ZSBzdWJtYXJrZXQsIHdoaWNoIGlzIGFyb3VuZCA1MCUgaGlnaGVyIGluIHRlcm1zIG9mIGVmZmVjdGl2ZSBwcmljZSBwZXIgc3FhdXJlLiBBdmVyYWdlIGVmZmVjdGl2ZSBwcmljZSBwZXIgc3FhdXJlIGluIEF1c3Rpbi1Sb3VuZCBSb2NrLCBUZXhhcyBpcyBhcm91bmQgXCQxLjUgaW4gU2VwdGVtYmVyIDIwMTkuIEluIEFrcm9uLCBPSCwgS2VudC9Qb3J0YWdlIENvdW50eSBpcyB0aGUgbW9zdCBleHBlbnNpdmUgc3VibWFya2V0LCB3aGljaCBpcyBhcm91bmQgMTAlIGhpZ2hlciBpbiB0ZXJtcyBvZiBlZmZlY3RpdmUgcHJpY2UgcGVyIHNxdWFyZS4gQXZlcmFnZSBlZmZlY3RpdmUgcHJpY2UgcGVyIHNxdWFyZSBpbiBBa3JvbiwgT0ggaXMgYXJvdW5kIFwkMS4wIGluIFNlcHRlbWJlciwgMjAxOS4KClRoZSBhdmVyYWdlIGNvbmNlc3Npb24gcGVyY2VudGFnZSBpcyBhcm91bmQgMSUgaW4gYm90aCBUZXhhcyBhbmQgT2hpbyBtYXJrZXQsIGFuZCB0aGUgYXZlcmFnZSBvY2N1cGFuY3kgcmF0ZSBpcyBhcm91bmQgOTIlIGluIFRleGFzIGFuZCA5NSUgaW4gT2hpby4KCkluIHRoaXMgYW5hbHlzaXMsIEkgaW1wbGVtZW50IHVuaWZvcm0gd2VpZ2h0cyB0byBjYWxjYWx1dGUgYXZlcmFnZXMgZm9yIHNpbXBsaWNpdHkuIEhvd2V2ZXIsIHRoZSBhbmFseXNpcyBjb3VsZCBiZSBtb3JlIGFjY3VyYXRlIGlmIHdlIGNhbGN1bGF0ZSBhdmVyYWdlIGVmZmVjdGl2ZSBwcmljZSBwZXIgc3F1YXJlIHdlaWdodGVkIGJ5IHRvdGFsIHNxdWFyZXMgKFF1YW50aXR5XCpBcmVhUGVyVW5pdCksIGF2ZXJhZ2Ugb2NjdXBhbmN5IHJhdGUgd2VpZ2h0ZWQgYnkgUXVhbnRpdHksIGFuZCBhdmVyYWdlIGNvbmNlc3Npb24gcGVyY2VudGFnZSB3ZWlnaHRlZCBieSBtb250aGx5IHRvdGFsIGFza2luZyBwcmljZSBvZiBhdmFpbGFibGUgdW5pdHMgaW4gYnVpbGRpbmcgKCgxLU9jY3VwYW5jeV9yYXRlKVwqUXVhbnRpdHlcKmFza2luZ19yZW50KS4KCkFsc28sIGlmIEkgaGF2ZSBtb3JlIHRpbWUsIEkgd2lsbCBhbmFseXplIG1hbmFnZW1lbnQgY29tcGFuaWVzIGluIG1hcmtldHMuIEZvciBleGFtcGxlLCB3aGljaCBtYW5hZ2VtZW50IGNvbXBhbmllcyBtYW5hZ2UgbHV4dXJ5IGJ1aWxkaW5nPyBXaGljaCBtYW5hZ2VtZW50IGNvbXBhbmllcyBhcmUgdGhlIG1vc3QgcG9wdWxhciBvbmVzIGluIG1hcmtldHM/IFdoaWNoIG1hbmFnZW1lbnQgY29tcGFuaWVzIGhhdmUgdGhlIGxhcmdlc3QgYXNzZXRzPyBBbmQgd2hpY2ggbWFuYWdlbWVudCBjb21wYW5pZXMgaGF2ZSB0aGUgYmVzdCBncmFkZXMgaW4gbWFya2V0cz8KCgoKCg==